local function MakeHat(name)
    local fns = {}
    local fname = name
    local symname = name
    local prefabname = symname

    local swap_data = { bank = symname, anim = "anim" }

    -- 穿戴基础
    local function _base_onequip(inst, owner, symbol_override, swap_hat_override)
        local skin_build = inst:GetSkinBuild()
        if skin_build ~= nil then
            owner:PushEvent("equipskinneditem", inst:GetSkinName())
            owner.AnimState:OverrideItemSkinSymbol(swap_hat_override or "swap_hat", skin_build, symbol_override or "swap_hat", inst.GUID, fname)
        else
            owner.AnimState:OverrideSymbol(swap_hat_override or "swap_hat", fname, symbol_override or "swap_hat")
        end

        if inst.components.fueled ~= nil then
            inst.components.fueled:StartConsuming()
        end

        if inst.skin_equip_sound and owner.SoundEmitter then
            owner.SoundEmitter:PlaySound(inst.skin_equip_sound)
        end
    end

    -- 穿戴基础
    local function _onequip(inst, owner, symbol_override, headbase_hat_override)
        _base_onequip(inst, owner, symbol_override)

        owner.AnimState:ClearOverrideSymbol("headbase_hat") -- 清除之前的覆盖
        if headbase_hat_override ~= nil then
            local skin_build = owner.AnimState:GetSkinBuild()
            if skin_build ~= "" then
                owner.AnimState:OverrideSkinSymbol("headbase_hat", skin_build, headbase_hat_override)
            else
                local build = owner.AnimState:GetBuild()
                owner.AnimState:OverrideSymbol("headbase_hat", build, headbase_hat_override)
            end
        end

        owner.AnimState:Show("HAT")
        owner.AnimState:Show("HAIR_HAT")
        owner.AnimState:Hide("HAIR_NOHAT")
        owner.AnimState:Hide("HAIR")

        if owner:HasTag("player") then
            owner.AnimState:Hide("HEAD")
            owner.AnimState:Show("HEAD_HAT")
            owner.AnimState:Show("HEAD_HAT_NOHELM")
            owner.AnimState:Hide("HEAD_HAT_HELM")
        end
    end

    -- 摘下
    local function _onunequip(inst, owner)
        local skin_build = inst:GetSkinBuild()
        if skin_build ~= nil then
            owner:PushEvent("unequipskinneditem", inst:GetSkinName())
        end

        owner.AnimState:ClearOverrideSymbol("headbase_hat") -- 它可能已经被 _onequip 覆盖
        if owner.components.skinner ~= nil then
            owner.components.skinner.base_change_cb = owner.old_base_change_cb
        end

        owner.AnimState:ClearOverrideSymbol("swap_hat")
        owner.AnimState:Hide("HAT")
        owner.AnimState:Hide("HAIR_HAT")
        owner.AnimState:Show("HAIR_NOHAT")
        owner.AnimState:Show("HAIR")

        if owner:HasTag("player") then
            owner.AnimState:Show("HEAD")
            owner.AnimState:Hide("HEAD_HAT")
            owner.AnimState:Hide("HEAD_HAT_NOHELM")
            owner.AnimState:Hide("HEAD_HAT_HELM")
        end

        if inst.components.fueled ~= nil then
            inst.components.fueled:StopConsuming()
        end
    end

    -- 并没有实施,可以直接使用 _onequip 函数
    fns.simple_onequip = function(inst, owner, from_ground)
        _onequip(inst, owner)
    end

    -- 并没有实施,可以直接使用 _onunequip 函数
    fns.simple_onunequip = function(inst, owner, from_ground)
        _onunequip(inst, owner)
    end

    -- 穿戴不隐藏头发
    fns.opentop_onequip = function(inst, owner)
        _base_onequip(inst, owner)

        owner.AnimState:Show("HAT")
        owner.AnimState:Hide("HAIR_HAT")
        owner.AnimState:Show("HAIR_NOHAT")
        owner.AnimState:Show("HAIR")

        owner.AnimState:Show("HEAD")
        owner.AnimState:Hide("HEAD_HAT")
        owner.AnimState:Hide("HEAD_HAT_NOHELM")
        owner.AnimState:Hide("HEAD_HAT_HELM")
    end

    -- 穿戴隐藏整个脸部
    fns.fullhelm_onequip = function(inst, owner)
        if owner:HasTag("player") then
            _base_onequip(inst, owner, nil, "headbase_hat")

            owner.AnimState:Hide("HAT")
            owner.AnimState:Hide("HAIR_HAT")
            owner.AnimState:Hide("HAIR_NOHAT")
            owner.AnimState:Hide("HAIR")

            owner.AnimState:Hide("HEAD")
            owner.AnimState:Show("HEAD_HAT")
            owner.AnimState:Hide("HEAD_HAT_NOHELM")
            owner.AnimState:Show("HEAD_HAT_HELM")

            owner.AnimState:HideSymbol("face")
            owner.AnimState:HideSymbol("swap_face")
            owner.AnimState:HideSymbol("beard")
            owner.AnimState:HideSymbol("cheeks")

            owner.AnimState:UseHeadHatExchange(true)
        else
            _base_onequip(inst, owner)

            owner.AnimState:Show("HAT")
            owner.AnimState:Hide("HAIR_HAT")
            owner.AnimState:Hide("HAIR_NOHAT")
            owner.AnimState:Hide("HAIR")
        end
    end

    -- 隐藏整个脸部,摘下之后的恢复函数
    fns.fullhelm_onunequip = function(inst, owner)
        _onunequip(inst, owner)

        if owner:HasTag("player") then
            owner.AnimState:ShowSymbol("face")
            owner.AnimState:ShowSymbol("swap_face")
            owner.AnimState:ShowSymbol("beard")
            owner.AnimState:ShowSymbol("cheeks")

            owner.AnimState:UseHeadHatExchange(false)
        end
    end

    fns.simple_onequiptomodel = function(inst, owner, from_ground)
        if inst.components.fueled ~= nil then
            inst.components.fueled:StopConsuming()
        end
    end

    local _skinfns = {
        simple_onequip = fns.simple_onequip,
        simple_onunequip = fns.simple_onunequip,
        opentop_onequip = fns.opentop_onequip,
        fullhelm_onequip = fns.fullhelm_onequip,
        fullhelm_onunequip = fns.fullhelm_onunequip,
        simple_onequiptomodel = fns.simple_onequiptomodel,
    }

    local function simple(custom_init)
        local inst = CreateEntity()

        inst.entity:AddTransform()
        inst.entity:AddAnimState()
        inst.entity:AddNetwork()

        MakeInventoryPhysics(inst)

        inst.AnimState:SetBank(symname)
        inst.AnimState:SetBuild(fname)
        inst.AnimState:PlayAnimation("anim")

        inst:AddTag("hat")

        inst:AddComponent("snowmandecor")

        if custom_init ~= nil then
            custom_init(inst)
        end

        MakeInventoryFloatable(inst)
        inst.components.floater:SetBankSwapOnFloat(false, nil, swap_data)

        inst.entity:SetPristine()

        if not TheWorld.ismastersim then
            return inst
        end

        inst._skinfns = _skinfns

        inst:AddComponent("inventoryitem")

        inst:AddComponent("inspectable")

        inst:AddComponent("tradable")

        inst:AddComponent("equippable")
        inst.components.equippable.equipslot = EQUIPSLOTS.HEAD
        inst.components.equippable:SetOnEquip(fns.simple_onequip)
        inst.components.equippable:SetOnUnequip(fns.simple_onunequip)
        inst.components.equippable:SetOnEquipToModel(fns.simple_onequiptomodel)

        MakeHauntableLaunch(inst)

        return inst
    end

    local function default()
        return simple()
    end

    -- 暗影之冕
    local function sw_shadow_crown_custom_init(inst)
        inst:AddTag("open_top_hat")

        inst:AddTag("gestaltprotection")

        inst:AddTag("shadowdominance")

        inst:AddTag("nightvision")
    end

    local function sw_shadow_crown_activate(inst, owner)
        if inst._is_active then
            return
        end
        inst._is_active = true

        if inst._task ~= nil then
            inst._task:Cancel()
            inst._task = nil
        end

        _onunequip(inst, owner) -- 隐藏佩戴图层

        if inst._front == nil then
            local skin_build = inst:GetSkinBuild()
            if skin_build ~= nil and skin_build == "sw_shadow_crown_skin1" then
                inst._front = SpawnPrefab("sw_shadow_crown_equipped", "sw_shadow_crown_equipped_skin1")
            elseif skin_build ~= nil and skin_build == "sw_shadow_crown_skin2" then
                inst._front = SpawnPrefab("sw_shadow_crown_equipped", "sw_shadow_crown_equipped_skin2")
            else
                inst._front = SpawnPrefab("sw_shadow_crown_equipped")
            end
            inst._front:OnActivated(owner, true)
        end
        if inst._back == nil then
            local skin_build = inst:GetSkinBuild()
            if skin_build ~= nil and skin_build == "sw_shadow_crown_skin1" then
                inst._back = SpawnPrefab("sw_shadow_crown_equipped", "sw_shadow_crown_equipped_skin1")
            elseif skin_build ~= nil and skin_build == "sw_shadow_crown_skin2" then
                inst._back = SpawnPrefab("sw_shadow_crown_equipped", "sw_shadow_crown_equipped_skin2")
            else
                inst._back = SpawnPrefab("sw_shadow_crown_equipped")
            end
            inst._back:OnActivated(owner, false)
        end

        -- local skin_build = inst:GetSkinBuild()
        -- if skin_build then
        --     inst._front:SetSkin(skin_build, inst.GUID)
        --     inst._back:SetSkin(skin_build, inst.GUID)
        -- end
    end

    local function sw_shadow_crown_onequip(inst, owner)
        fns.opentop_onequip(inst, owner)

        sw_shadow_crown_activate(inst, owner)
    end

    local function sw_shadow_crown_onunequip(inst, owner)
        inst._is_active = false

        if inst._task then
            inst._task:Cancel()
            inst._task = nil
        end

        _onunequip(inst, owner)
        if inst._front ~= nil then
            inst._front:Remove()
            inst._front = nil
        end
        if inst._back ~= nil then
            inst._back:Remove()
            inst._back = nil
        end
    end

    local function sw_shadow_crown_onremove(inst)
        if inst._front ~= nil and inst._front:IsValid() then
            inst._front:Remove()
        end
        if inst._back ~= nil and inst._back:IsValid() then
            inst._back:Remove()
        end
    end

    fns.sw_shadow_crown = function()
        local inst = simple(sw_shadow_crown_custom_init)

        inst.components.floater:SetSize("med")
        inst.components.floater:SetScale(0.68)

        if not TheWorld.ismastersim then
            return inst
        end

        inst.components.equippable:SetOnEquip(sw_shadow_crown_onequip)
        inst.components.equippable:SetOnUnequip(sw_shadow_crown_onunequip)

        inst:AddComponent("shadowlevel")
        inst.components.shadowlevel:SetDefaultLevel(TUNING.SKELETONHAT_SHADOW_LEVEL)

        inst:AddComponent("shadowdominance")

        MakeHauntableLaunchAndPerish(inst)

        inst:ListenForEvent("onremove", sw_shadow_crown_onremove)

        return inst
    end

    -----------------------------------------------------------------------------

    local fn = nil
    local assets = { Asset("ANIM", "anim/" .. fname .. ".zip") }
    local prefabs = nil

    if name == "sw_shadow_crown" then
        prefabs = {
            "sw_shadow_crown_equipped",
        }
        fn = fns.sw_shadow_crown
    end

    table.insert(ALL_HAT_PREFAB_NAMES, prefabname)

    return Prefab(prefabname, fn or default, assets, prefabs)
end

return MakeHat("sw_shadow_crown")
